package com.yt.lxh.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yt.lxh.common.exception.ServiceException;
import com.yt.lxh.common.exception.SqlHandlerException;
import com.yt.lxh.common.result.ResultCodeEnum;
import com.yt.lxh.common.service.CacheService;
import com.yt.lxh.common.service.CheckLogin;
import com.yt.lxh.common.service.MinioService;
import com.yt.lxh.constant.ProductConstant;
import com.yt.lxh.constant.SQLConstant;
import com.yt.lxh.model.acl.Admin;
import com.yt.lxh.vo.product.CategoryVO;
import com.yt.lxh.model.product.Category;
import com.yt.lxh.dto.product.ListCategoryDTO;
import com.yt.lxh.dto.product.SaveCategoryDTO;
import com.yt.lxh.dto.product.UpdateCategoryDTO;
import com.yt.lxh.product.mapper.CategoryMapper;
import com.yt.lxh.product.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService {

    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private CacheService cacheService;

    @Autowired
    private MinioService minioService;

    @Autowired
    private CheckLogin checkLogin;

    /**
     * 添加类别
     * @param categoryVO 类别信息
     */
    @Override
    public void addCategory(SaveCategoryDTO saveCategoryDTO, String token) {
        // 获取用户信息
//        Admin admin = checkLogin.checkAdminLogin();
        final Admin admin = new Admin();
        admin.setUsername("测试");
        Category category = BeanUtil.copyProperties(saveCategoryDTO, Category.class);
        String fileName;
        // 上传文件到阿里云OSS
        if (saveCategoryDTO.getFile() != null && !saveCategoryDTO.getFile().isEmpty()) {
            fileName = minioService.uploadByFile(saveCategoryDTO.getFile());
            category.setCategoryImage(fileName);
        }
        //补全其他数据
        category.setCreateUser(admin.getUsername());
        category.setUpdateUser(admin.getUsername());
        // 新增数据
        int row = categoryMapper.insert(category);
        if (row == 0) {
            throw new SqlHandlerException(SQLConstant.INSERT_FAIL + " ---> CategoryServiceImpl.addCategory");
        }
        // 启用状态下，才去更新缓存
        if (category.getEnable())
            // 更新缓存
            saveCategoryToCache();
    }

    /**
     * 获取全部类别数据
     */
    @Override
    public PageInfo<Category> getCategoryPage(ListCategoryDTO listCategoryDTO) {
        // 分页数据处理
        PageHelper.startPage(listCategoryDTO.getPageNum(), listCategoryDTO.getPageSize());
        LambdaQueryWrapper<Category> wrapper = Wrappers.<Category>lambdaQuery()
                // 查询全部  isAll 为 true，忽略 eq() 条件
                // 查询未启用 / 查询已启用 ---> isAll 为 false，根据 enable 查询
                .eq(!listCategoryDTO.getIsAll(), Category::getEnable, listCategoryDTO.getEnable())
                // 模糊查询
                .like(StrUtil.isNotBlank(listCategoryDTO.getQueryField()),
                        Category::getCategoryName, listCategoryDTO.getQueryField())
                .orderByDesc(Category::getUpdateTime, Category::getSort);
        List<Category> categories = categoryMapper.selectList(wrapper);
        return new PageInfo<>(categories);
    }

    /**
     * 获取启用状态类别数据列表
     * @return
     */
    @Override
    public List<CategoryVO> getCategoryListByEnableIsTrue() {
        // 从缓存获取数据
        String categoriesJson = getCategoryByCache();
        // 判断缓存是否存在
        if (StrUtil.isBlank(categoriesJson)) {
            // 不存在，重新查询数据库，并将数据存入缓存
            return saveCategoryToCache();
        } else {
            // 存在，直接返回
            return JSON.parseArray(categoriesJson, CategoryVO.class);
        }
    }

    /**
     * 更新类别
     * @param category 类别信息
     */
    @Override
    public void updateCategory(UpdateCategoryDTO updateCategoryDTO, String token) {
        // 获取用户信息
        Admin admin = checkLogin.checkAdminLogin();
        Category category = categoryMapper.selectById(updateCategoryDTO.getId());
        if (category == null)
            // 前端传的ID查不到数据，抛出“数据不存在”异常
            throw new ServiceException(ResultCodeEnum.DATA_NOT_EXIST);
        // 删除阿里云OSS保存的旧文件
        if (StrUtil.isNotBlank(updateCategoryDTO.getOldFileName())) {
            minioService.removeFile(updateCategoryDTO.getOldFileName());
        }
        String fileName = null;
        // 保存新文件
        if (updateCategoryDTO.getFile() != null && !updateCategoryDTO.getFile().isEmpty()) {
            fileName = minioService.uploadByFile(updateCategoryDTO.getFile());
        }
        // 根据ID更新
        int row = categoryMapper.update(null, Wrappers.<Category>lambdaUpdate()
                .set(Category::getCategoryName, updateCategoryDTO.getCategoryName())
                .set(Category::getCategoryMark, updateCategoryDTO.getCategoryMark())
                .set(fileName != null, Category::getCategoryImage, fileName)
                .set(Category::getDescription, updateCategoryDTO.getDescription())
                .set(Category::getEnable, updateCategoryDTO.getEnable())
                .set(Category::getSort, updateCategoryDTO.getSort())
                .set(Category::getUpdateUser, admin.getUsername())
                .eq(Category::getId, updateCategoryDTO.getId())
        );

        if (row == 0)
            throw new ServiceException(ResultCodeEnum.DATA_NOT_EXIST);
        // 更新缓存
        saveCategoryToCache();
    }

    /**
     * 根据ID逻辑删除类别数据
     * @param categoryId 类别ID
     */
    @Override
    public void removeCategoryById(String categoryId, String token) {
        // 获取用户信息
        Admin admin = checkLogin.checkAdminLogin();
        if (categoryId == null)
            // ID为空，抛出“缺少参数”异常
            throw new ServiceException(ResultCodeEnum.PARAM_REQUIRE);
        Category category = categoryMapper.selectById(categoryId);
        if (category == null)
            // 前端传的ID查不到数据，抛出“数据不存在”异常
            throw new ServiceException(ResultCodeEnum.DATA_NOT_EXIST);
        // 删除阿里云OSS保存的旧文件
        if (StrUtil.isNotBlank(category.getCategoryImage())) {
            minioService.removeFile(category.getCategoryImage());
        }
        // 更新
        int row = categoryMapper.update(null, Wrappers.<Category>lambdaUpdate()
                    .set(Category::getIsDeleted, SQLConstant.DELETED)
                    .set(Category::getUpdateUser, admin.getUsername())
                    .eq(Category::getId, categoryId));
        if (row == 0)
            throw new SqlHandlerException("数据库更新记录为 0 ---> CategoryServiceImpl.removeCategoryById");
    }

    /**
     * 将最新的类别数据存入缓存
     */
    private List<CategoryVO> saveCategoryToCache() {
        // 类别数据在缓存中的标识  Luxuehe_CATEGORY
        String cacheKey = ProductConstant.CATEGORY_CACHE_KEY;
        // 删除缓存中的旧数据
        cacheService.delete(cacheKey);
        // 查询新数据，且类别已启用
        List<Category> categories = categoryMapper.selectList(Wrappers.<Category>lambdaQuery()
                .eq(Category::getEnable, ProductConstant.CATEGORY_ENABLE)
                .orderByDesc(Category::getSort));
        // 没有记录，缓存 null
        if (categories == null && categories.size() == 0)
            cacheService.set(cacheKey, null);
        // 处理返回的数据，剔除多余字段数据
        List<CategoryVO> categoryVOS = categories.stream()
                .map(item -> BeanUtil.copyProperties(item, CategoryVO.class))
                .collect(Collectors.toList());
        // 将新数据存入缓存
        cacheService.set(cacheKey, JSON.toJSONString(categoryVOS));
        return categoryVOS;
    }

    /**
     * 从缓存获取类别数据
     */
    private String getCategoryByCache() {
        // 类别数据在缓存中的标识  Luxuehe_CATEGORY
        String cacheKey = ProductConstant.CATEGORY_CACHE_KEY;
        String categoriesJson = cacheService.get(cacheKey);
        if (StrUtil.isBlank(categoriesJson)) return null;
        return categoriesJson;
    }

}
